package framework.model;

public abstract class Account implements IAccount {

    private int accountNumber;
    private double currentBalance;
    protected double interestRate;
    //
    protected SelectiveList<Entry, Double> entries;
    protected Customer customer;
    //
    static int ACCT_NUM_TRACKING = 0;
    //

    public Account(Customer customer) {
        this.customer = customer;
        this.accountNumber = ++ACCT_NUM_TRACKING;
        interestRate = Constant.DEFAULT_INTEREST_RATE;
        entries = new SelectiveList<>();
    }

    public void addInterest() {
        if(currentBalance > 0) {
            double newBalance = currentBalance + calculateInterest();
            updateBalance(newBalance);
        }
    }

    protected double calculateInterest() {
        return (getInterestRate() * currentBalance);
    }

    private void updateBalance(double newBalance) {
        currentBalance = newBalance;
    }

    public double getInterestRate() {
        return interestRate;
    }

    public void executeTransaction(Entry e) {
        currentBalance += e.getAmount();
        entries.add(e);
        notifyCustomer(createNotification(e));
    }
    //  To be override functions

    public String createNotification(Entry e) {
        return "Transaction is executed, amount: " + e.getAmount();
    }

    public String generateMonthlyReport() {
        return "Not supported yet.";
    }

    // Override sections
    @Override
    public double getCurrentBalance() {
        return currentBalance;
    }

    @Override
    public void notifyCustomer(String msg) {
        if (msg != null) {
            customer.sendNotification(msg);
        }
    }

    @Override
    public void addEntry(Entry e) {
        entries.add(e);
    }

    @Override
    public void deposit(Entry e) {
        // @TODO: make sure there is no negative or throw exception
        e.setAmount(Math.abs(e.getAmount()));
        this.executeTransaction(e);
    }

    @Override
    public void withdraw(Entry e) {
        e.setAmount((-1) * Math.abs(e.getAmount()));
        this.executeTransaction(e);
    }

    @Override
    public Customer getCustomer() {
        return customer;
    }
}